
#ifndef _TSOC_SCENE_
#define _TSOC_SCENE_

#include "Math.hpp"
#include "Color.hpp"

#include <gsl/gsl_qrng.h>

#include <stdint.h>
#include <string>
#include <vector>

#define TRIANGLE_FLAG_USER_VISIBLE	1

#define TSOC_MATERIAL_TEXTURE_COLOR	1
#define TSOC_MATERIAL_TEXTURE_NORMAL	2
#define TSOC_MATERIAL_REFLECTION		4
#define TSOC_MATERIAL_EMITTER			8


namespace com
{
	namespace toxiclabs
	{
		namespace tsoc
		{
					
			/*!
			 * Camera class 
			 */ 
			class Camera
			{
				public:
				
					/*! Empty constructor, creates
					 * a camera with default values
					 * */
					Camera();
					Camera(std::string & name,Vector & position,Vector & target,float angle,float near,float far);
				
					void CreateMatrix();
					
					/*! camera name*/
					std::string name;
					
					/*! camera transformation matrix */
					Matrix matrix;
					
					/*! near depth of field */
					float near;
					
					/*! far depth of field */
					float far;
					
					
					//folowing values are stored for debug purposes
					float angle;
					
					Vector position;
					Vector target;
					
			};
			 
			/*!
			 * 2D Texture for either diffuse or bump maps
			 */ 
			class Texture
			{
				private:
					Texture();
					
				public:
					uint8_t * data;
					int width;
					int height;
					
					uint8_t type;
					
					/*! Loads an image file and creates 
					 * a Texture object
					 */
					static Texture * Load(const char * filename);
					
					/*!
					 * Gets diffuse value at u,v
					*/
					Color Texel(float u,float v);
					
					/*!
					 * Gets normal at u,v
					 */ 
					Vector Bump(float u,float v);
			};
			
			
			
			/*!
			 * Triangle class
			 * It just allocates triangle data
			 */ 
			class Triangle
			{
				public:
					
					
					Vector vertex[3];
					
					struct
					{
						float u;
						float v;
					}texture[3];
					
					Vector normal[3];
				
					Vector pnormal;//computed plane normal
					
					uint8_t material_id;
			};
			
			class Light
			{
				public:
					std::string name;
				
					Color color;
					float power;
					float angle;
						
					std::vector<Triangle * > triangles;
				
					gsl_qrng * q_direction;
					gsl_qrng * q_position;
				
					Light();
					~Light();
					
			};
			
			/*!
			 * Material class
			 */ 
			class Material
			{
				public:
					Material();
				
					std::string name;
					Color diffuse;
					Color specular;
										
					/* used for roussian roulete, computed using distance of diffuse + specular */
					float diffuse_factor;
					float specular_factor;
					float absorption_factor;
					
					float reflection;
					float transparency;
				
					Texture * texture_kd;
					Texture * texture_normal;
					
					Light * light;
				
					uint32_t flags;
			};
			
			/*!
			 * This class groups all scene elements
			 */ 
			class Scene
			{
				public:
					Scene();
					virtual ~Scene();
					
					void ApplyCamera();
					
					std::vector<Triangle *> triangles;
					std::vector<Material *> materials;
					std::vector<Light *> lights;
					std::vector<Camera *> cameras;
			};
		}
	}
}


#endif
